/**
 * ipassbook 0.6.0
 * Copyright (C)2009 wateray and contributors
 * wateray@gmail.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

package com.wateray.ipassbook.kernel.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ibatis.dao.client.DaoManager;
import com.wateray.ipassbook.ApplicationConfig;
import com.wateray.ipassbook.commom.CommomTool;
import com.wateray.ipassbook.commom.Constant;
import com.wateray.ipassbook.domain.PassbookDetail;
import com.wateray.ipassbook.domain.Receipt;
import com.wateray.ipassbook.domain.form.ReceiptForm;
import com.wateray.ipassbook.kernel.event.IPassbookEvent;
import com.wateray.ipassbook.kernel.event.IPassbookEventType;
import com.wateray.ipassbook.kernel.event.IPassbookObserver;
import com.wateray.ipassbook.persistence.DaoConfig;
import com.wateray.ipassbook.persistence.iface.ReceiptDao;

/**
 * @author wateray
 * @create 2009-5-24
 */
public class ReceiptService {
	private ReceiptDao receiptDao;
	private DaoManager daoMgr;

	private PassbookService passbookService = new PassbookService();

	public ReceiptService() {
		daoMgr = DaoConfig.getDaoManager();
		this.receiptDao = (ReceiptDao) daoMgr.getDao(ReceiptDao.class);

	}

	public ReceiptService(DaoManager daoMgr, ReceiptDao receiptDao) {
		this.daoMgr = daoMgr;
		this.receiptDao = receiptDao;
	}

	public List<ReceiptForm> getReceiptFormList(String beginDay, String endDay) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("language", ApplicationConfig.getLang());
		map.put("beginDay", beginDay);
		map.put("endDay", endDay);

		return receiptDao.getReceiptFormList(map);
	}

	public ReceiptForm getReceiptFormById(String receiptId) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("language", ApplicationConfig.getLang());
		map.put("receiptId", receiptId);

		return receiptDao.getReceiptFormById(map);
	}

	public String insertReceipt(Receipt receipt) {
		int result = 0;
		String maxId;
		try {
			daoMgr.startTransaction();

			// maxId
			maxId = receiptDao.getReceiptMaxId();
			maxId = CommomTool.plusOneFillZero(maxId, 10);
			receipt.setReceiptId(maxId);
			result = receiptDao.insertReceipt(receipt);
			PassbookDetail passbookDetail = passbookService
					.getDefaultPassbookDetailById(receipt.getPassbookId());

			// balance
			double balance = passbookDetail.getBalance();
			if (receipt.getReceiptFlag().equals(Constant.EXPENSE_KBN)) {
				balance = balance - receipt.getAmount();
			} else {
				balance = balance + receipt.getAmount();
			}

			passbookDetail.setBalance(balance);
			result += passbookService
					.updatePassbookDetailBalance(passbookDetail);

			daoMgr.commitTransaction();
			// invoke
			IPassbookObserver.getInstance().notifyEvents(
					new IPassbookEvent(this,
							IPassbookEventType.PassbookTableModifyEvent));
		} finally {
			daoMgr.endTransaction();
		}
		return maxId;
	}

	public int updateReceipt(Receipt newReceipt) {
		int result = 0;
		try {
			daoMgr.startTransaction();
			ReceiptForm oldReceiptForm = getReceiptFormById(newReceipt
					.getReceiptId());

			// Change income to expense or expense to income; income income;
			// expense expense;
			double beforeAmount = oldReceiptForm.getAmount()
					* (oldReceiptForm.getReceiptFlag().equals(
							Constant.EXPENSE_KBN) ? -1 : 1);
			double afterAmount = newReceipt.getAmount()
					* (newReceipt.getReceiptFlag().equals(Constant.EXPENSE_KBN) ? -1
							: 1);
			double diffAmout = afterAmount - beforeAmount;

			// Retrieve old passbook and new passbook.
			PassbookDetail oldPassbookDetail = passbookService
					.getPassbookDetailById(oldReceiptForm.getPassbookId(),
							oldReceiptForm.getPassbookSubId());
			PassbookDetail passbookDetail = passbookService.getPassbookDetailById(newReceipt.getPassbookId(),
							newReceipt.getPassbookSubId());
			
			// If passbook has been changed.
			if (!oldPassbookDetail.equals(passbookDetail)) {
				// update old passbook balance
				double b = oldPassbookDetail.getBalance() - beforeAmount;
				oldPassbookDetail.setBalance(b);
				passbookService.updatePassbookDetailBalance(oldPassbookDetail);

				// update new passbook balance
				b = 0;
				b = passbookDetail.getBalance() + afterAmount;
				passbookDetail.setBalance(b);
				passbookService.updatePassbookDetailBalance(passbookDetail);
				
				// invoke
				IPassbookObserver.getInstance().notifyEvents(
						new IPassbookEvent(this,
								IPassbookEventType.PassbookTableModifyEvent));
			} else if (diffAmout != 0) {
				passbookDetail = passbookService
						.getDefaultPassbookDetailById(newReceipt
								.getPassbookId());

				// balance
				double balance = passbookDetail.getBalance();
				balance = balance + diffAmout;

				passbookDetail.setBalance(balance);
				result += passbookService
						.updatePassbookDetailBalance(passbookDetail);
				// invoke
				IPassbookObserver.getInstance().notifyEvents(
						new IPassbookEvent(this,
								IPassbookEventType.PassbookTableModifyEvent));
			}

			result += receiptDao.updateReceipt(newReceipt);

			daoMgr.commitTransaction();
		} finally {
			daoMgr.endTransaction();
		}
		return result;
	}

	public int deleteReceipt(Receipt receipt) {
		int result = 0;
		try {
			daoMgr.startTransaction();

			PassbookDetail passbookDetail = passbookService
					.getDefaultPassbookDetailById(receipt.getPassbookId());

			// balance
			double balance = passbookDetail.getBalance();
			if (receipt.getReceiptFlag().equals(Constant.EXPENSE_KBN)) {
				balance = balance + receipt.getAmount();
			} else {
				balance = balance - receipt.getAmount();
			}

			passbookDetail.setBalance(balance);

			result += passbookService
					.updatePassbookDetailBalance(passbookDetail);

			result += receiptDao.deleteReceipt(receipt);

			daoMgr.commitTransaction();
			// invoke
			IPassbookObserver.getInstance().notifyEvents(
					new IPassbookEvent(this,
							IPassbookEventType.PassbookTableModifyEvent));
		} finally {
			daoMgr.endTransaction();
		}
		return result;
	}

	public static void main(String[] args) {
		ReceiptService service = new ReceiptService();
		// List<Passbook> list;
		// list = service.getPassbookList();
		// Iterator<Passbook> e = list.iterator();
		// while (e.hasNext()) {
		// Passbook entity = (Passbook) e.next();
		// System.out.println(" EntityId=" + entity.getEntityId()
		// + " EntityName=" + entity.getEntityName());
		// }

		service.getReceiptFormList("2009-05-01", "2009-06-01");
		// service.getReceiptFormById("0000000001");
	}
}
